package org.springframework.boot.autoconfigure.data.redis;

import com.autoconfigure.redis.properties.RedisConnectionProperties;
import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.boot.autoconfigure.cache.CacheManagerCustomizers;
import org.springframework.cache.CacheManager;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.serializer.Jackson2JsonRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializationContext;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;

import java.util.LinkedHashSet;
import java.util.List;

/**
 * @author lemon
 * @version 1.0
 * @description: 创建缓存管理器
 * @date Create by lemon on 2020-07-09 08:19
 */
@RequiredArgsConstructor
public abstract class AbstractCacheManagerFactory implements CacheManagerFactory {
    private final CacheManagerCustomizers customizerInvoker;

    /**
     * @param redisConnectionFactory
     * @param redisConnectionProperties
     * @return org.springframework.cache.CacheManager
     * @description 创建缓存管理器
     * @author lemon
     * @date 2020-07-09 15:51
     */
    @Override
    public CacheManager createCacheManager(RedisConnectionFactory redisConnectionFactory, RedisConnectionProperties redisConnectionProperties) {
        RedisCacheConfiguration config = RedisCacheConfiguration.defaultCacheConfig()
                .entryTtl(redisConnectionProperties.getTtl())
                .serializeKeysWith(redisConnectionProperties.getKeySerializationPair())
                .serializeValuesWith(redisConnectionProperties.getValueSerializationPair());

        if (redisConnectionProperties.getCacheNullValues() != null && !redisConnectionProperties.getCacheNullValues()) {
            config = config.disableCachingNullValues();
        }

        if (redisConnectionProperties.getUsePrefix() != null && !redisConnectionProperties.getUsePrefix()) {
            config = config.disableKeyPrefix();
        } else {
            if (redisConnectionProperties.getCacheKeyPrefix() != null) {
                config = config.prefixKeysWith(redisConnectionProperties.getCacheKeyPrefix().compute(redisConnectionProperties.getKeyPrefix()));
            } else {
                config = config.prefixKeysWith(redisConnectionProperties.getKeyPrefix());
            }
        }

        if (redisConnectionProperties.getConversionService() != null) {
            config = config.withConversionService(redisConnectionProperties.getConversionService());
        }

        RedisCacheManager.RedisCacheManagerBuilder cacheManagerBuilder = RedisCacheManager.builder(redisConnectionFactory)
                .cacheDefaults(config);

        List<String> cacheNames = redisConnectionProperties.getCacheNames();

        if (!cacheNames.isEmpty()) {
            cacheManagerBuilder.initialCacheNames(new LinkedHashSet<>(cacheNames));
        }

        return this.customizerInvoker.customize(cacheManagerBuilder.build());
    }
}
